package service

import (
	"admin-nexus-backend/internal/dto"
	"admin-nexus-backend/internal/model"
	"errors"

	"gorm.io/gorm"
)

type ResourceService struct {
	db *gorm.DB
}

func NewResourceService(db *gorm.DB) *ResourceService {
	return &ResourceService{db: db}
}

// GetResourceList 获取资源列表
func (s *ResourceService) GetResourceList(params *dto.ResourceQueryParams) ([]model.Resource, error) {
	var resources []model.Resource

	query := s.db.Model(&model.Resource{})

	// 条件查询
	if params.Name != "" {
		query = query.Where("name LIKE ?", "%"+params.Name+"%")
	}
	if params.Code != "" {
		query = query.Where("code LIKE ?", "%"+params.Code+"%")
	}
	if params.Type != nil {
		query = query.Where("type = ?", *params.Type)
	}
	if params.Status != nil {
		query = query.Where("status = ?", *params.Status)
	}

	if err := query.Order("sort ASC, id ASC").Find(&resources).Error; err != nil {
		return nil, err
	}

	return resources, nil
}

// GetResourceTree 获取资源树
func (s *ResourceService) GetResourceTree(params *dto.ResourceQueryParams) ([]*model.Resource, error) {
	resources, err := s.GetResourceList(params)
	if err != nil {
		return nil, err
	}

	return buildResourceTree(resources, 0), nil
}

// GetResourceByID 根据 ID 获取资源
func (s *ResourceService) GetResourceByID(id uint) (*model.Resource, error) {
	var resource model.Resource
	if err := s.db.First(&resource, id).Error; err != nil {
		return nil, err
	}
	return &resource, nil
}

// CreateResource 创建资源
func (s *ResourceService) CreateResource(req *dto.ResourceCreateRequest) error {
	// 检查资源编码是否存在
	var count int64
	if err := s.db.Model(&model.Resource{}).Where("code = ?", req.Code).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("资源编码已存在")
	}

	// 如果有父级资源，检查父级是否存在
	if req.ParentID > 0 {
		if err := s.db.First(&model.Resource{}, req.ParentID).Error; err != nil {
			return errors.New("父级资源不存在")
		}
	}

	// 创建资源
	resource := &model.Resource{
		ParentID:  req.ParentID,
		Type:      req.Type,
		Name:      req.Name,
		Code:      req.Code,
		Path:      req.Path,
		Component: req.Component,
		Icon:      req.Icon,
		Sort:      req.Sort,
		IsHidden:  req.IsHidden,
		IsCache:   req.IsCache,
		Status:    req.Status,
		Remark:    req.Remark,
	}

	return s.db.Create(resource).Error
}

// UpdateResource 更新资源
func (s *ResourceService) UpdateResource(id uint, req *dto.ResourceUpdateRequest) error {
	// 检查资源是否存在
	var resource model.Resource
	if err := s.db.First(&resource, id).Error; err != nil {
		return err
	}

	// 检查资源编码是否被其他资源使用
	if req.Code != "" && req.Code != resource.Code {
		var count int64
		if err := s.db.Model(&model.Resource{}).Where("code = ? AND id != ?", req.Code, id).Count(&count).Error; err != nil {
			return err
		}
		if count > 0 {
			return errors.New("资源编码已被使用")
		}
	}

	// 如果有父级资源，检查父级是否存在
	if req.ParentID > 0 && req.ParentID != resource.ParentID {
		// 不能将资源设置为自己的子资源
		if req.ParentID == id {
			return errors.New("不能将资源设置为自己的子资源")
		}

		if err := s.db.First(&model.Resource{}, req.ParentID).Error; err != nil {
			return errors.New("父级资源不存在")
		}
	}

	// 更新资源信息
	updates := map[string]interface{}{
		"parent_id": req.ParentID,
		"type":      req.Type,
		"name":      req.Name,
		"code":      req.Code,
		"path":      req.Path,
		"component": req.Component,
		"icon":      req.Icon,
		"sort":      req.Sort,
		"is_hidden": req.IsHidden,
		"is_cache":  req.IsCache,
		"status":    req.Status,
		"remark":    req.Remark,
	}

	return s.db.Model(&resource).Updates(updates).Error
}

// DeleteResource 删除资源
func (s *ResourceService) DeleteResource(id uint) error {
	// 检查是否有子资源
	var count int64
	if err := s.db.Model(&model.Resource{}).Where("parent_id = ?", id).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("该资源存在子资源，无法删除")
	}

	// 检查资源是否被角色使用
	if err := s.db.Model(&model.RoleResource{}).Where("resource_id = ?", id).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("该资源已被角色使用，无法删除")
	}

	return s.db.Transaction(func(tx *gorm.DB) error {
		// 删除角色资源关联
		if err := tx.Where("resource_id = ?", id).Delete(&model.RoleResource{}).Error; err != nil {
			return err
		}

		// 删除资源（软删除）
		if err := tx.Delete(&model.Resource{}, id).Error; err != nil {
			return err
		}

		return nil
	})
}

// BatchDeleteResource 批量删除资源
func (s *ResourceService) BatchDeleteResource(ids []uint) error {
	return s.db.Transaction(func(tx *gorm.DB) error {
		for _, id := range ids {
			// 检查是否有子资源
			var count int64
			if err := tx.Model(&model.Resource{}).Where("parent_id = ?", id).Count(&count).Error; err != nil {
				return err
			}
			if count > 0 {
				return errors.New("存在包含子资源的项，无法批量删除")
			}

			// 检查资源是否被角色使用
			if err := tx.Model(&model.RoleResource{}).Where("resource_id = ?", id).Count(&count).Error; err != nil {
				return err
			}
			if count > 0 {
				return errors.New("存在已被角色使用的资源，无法批量删除")
			}
		}

		// 删除角色资源关联
		if err := tx.Where("resource_id IN ?", ids).Delete(&model.RoleResource{}).Error; err != nil {
			return err
		}

		// 批量删除资源（软删除）
		if err := tx.Delete(&model.Resource{}, ids).Error; err != nil {
			return err
		}

		return nil
	})
}

// buildResourceTree 构建资源树
func buildResourceTree(resources []model.Resource, parentID uint) []*model.Resource {
	var tree []*model.Resource

	for i := range resources {
		if resources[i].ParentID == parentID {
			resource := &resources[i]

			// 递归查找子资源
			children := buildResourceTree(resources, resource.ID)
			if len(children) > 0 {
				resource.Children = children
			}

			tree = append(tree, resource)
		}
	}

	return tree
}
